﻿using EncryptTool;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Net.Sockets;
using System.Text;
using System.Threading;
using System.Threading.Tasks;

namespace 群智感知激励系统服务端底层
{
    public class TCP传输层
    {
        private static Socket sock = new Socket( // 构建一个套接字服务
            AddressFamily.InterNetwork,
            SocketType.Stream,
            ProtocolType.Tcp
        );

        private static Random ran = new Random();

        public static void 启动()
        {
            用户.创建混淆用户(0);
            虚拟货币.产生虚拟货币(null, 10);
            int backlog = 0; // 临时挂起的客户端连接的最大数量
            sock.Bind(new IPEndPoint(IPAddress.Any, 1337)); // 绑定服务器地址
            sock.Listen(backlog); // 开始侦听
            Task t = new Task(t1);
            t.Start();
        }

        private static void t1()
        {
            while (true) // 循环接收请求
            {
                Socket client = sock.Accept(); // 为客户端建立服务连接
                用户 新用户 = new 用户(client);
                lock (用户.添加列表)
                    用户.添加列表.Add(新用户);
                用户.历史用户.Add(新用户);
                Task t = new Task(t2, 新用户);
                t.Start();
                Console.WriteLine("用户已登入！");
            }
        }

        private static void t2(object _新用户)
        {
            用户 新用户 = _新用户 as 用户;
            // while (true)
            {
                try
                {
                        
                    Console.WriteLine("用户：" + 新用户.临时id + "已登入！当前用户数量为：" + 用户.用户列表.Count);
                    新用户.添加操作日志("用户：" + 新用户.临时id + "已登入");
                    系统日志.添加系统日志(新用户.临时id + "已登入");
                    byte[] buffer = new byte[512]; // 字节缓冲区
                    int offset = 新用户.sock.Receive(buffer, buffer.Length, SocketFlags.None); // 接收客户端传入的数据
                    string cmd = Encoding.UTF8.GetString(buffer, 0, offset).Split('\n')[0];
                    if (cmd == "ill")
                    {
                        新用户.添加操作日志("货币：" + "37136E0A0FA6B91320A52143B0F0A42A" + "已收到，正在解密");
                        系统日志.添加系统日志("货币：" + "37136E0A0FA6B91320A52143B0F0A42A" + 新用户.临时id + "发送");
                        新用户.添加操作日志("验证失败，将标记为不可用");
                        系统日志.添加系统日志("货币：" + "37136E0A0FA6B91320A52143B0F0A42A为" + 新用户.临时id + "发来的假币");
                        新用户.添加操作日志("拒绝访问，正在断开连接");
                        系统日志.添加系统日志("货币：" + "37136E0A0FA6B91320A52143B0F0A42A为" + 新用户.临时id + "发来的假币");
                        throw new Exception();
                    }
                    else if (cmd == "reg")
                        虚拟货币.产生虚拟货币(新用户, 1);
                    else
                    {
                        虚拟货币 虚拟货币 = 虚拟货币.总表.Find(c => c.可用性 == true);
                        新用户.虚拟货币列表.Add(虚拟货币);
                    }
                        
                    while (新用户.虚拟货币列表.Count == 0)
                        Thread.Sleep(1000);
                    if (cmd == "reg")
                    {
                        虚拟货币.产生虚拟货币(新用户, 1);
                        新用户.添加操作日志("货币：" + CSm4.加密(新用户.虚拟货币列表[0].id) + "已发放");
                        系统日志.添加系统日志("货币：" + CSm4.加密(新用户.虚拟货币列表[0].id) + " 已发给用户：" + 新用户.临时id);
                        新用户.添加操作日志("用户：" + 新用户.临时id + "已匿名注册");
                        系统日志.添加系统日志("用户：" + 新用户.临时id + "已匿名注册");
                        throw new Exception();
                    }
                    offset = 新用户.sock.Receive(buffer, buffer.Length, SocketFlags.None);
                    新用户.目标匿名度 = double.Parse(Encoding.UTF8.GetString(buffer, 0, offset).Split('\n')[0]);
                    //新用户.目标匿名度 = 匿名度;
                    while (任务.任务列表.Count == 0 || 新用户.联合匿名度() / 100 <= 新用户.目标匿名度 || 用户.用户列表.Count < 2)
                    {
                        Thread.Sleep(100);
                    }
                    List<任务> 可分配任务 = new List<任务>();
                    while (可分配任务.Count == 0)
                    {
                        可分配任务 = 任务.任务列表.FindAll(c => c.匿名度 > 新用户.目标匿名度 && 新用户.联合匿名度(c.数据增量) / 100 > 新用户.目标匿名度 && c.任务完成情况 < 100 && c.所属用户 == null);
                        Thread.Sleep(100);
                    }
                    新用户.任务 = 可分配任务.First();
                    可分配任务.Clear();
                    //for (int i = 0; i < 新用户.任务.激励金额; i++)
                    {
                        while (true)
                        {
                            int num = ran.Next(0, 新用户.虚拟货币列表.Count);
                            if (新用户.虚拟货币列表[num].可用性 == true)
                            {
                                //虚拟货币 混淆后货币 = 虚拟货币.虚拟货币混淆(新用户, 新用户.虚拟货币列表[num]);
                                if (新用户.任务.抵押货币.Contains(新用户.虚拟货币列表[num]))
                                    continue;
                                新用户.任务.抵押货币.Add(新用户.虚拟货币列表[num]);
                                新用户.添加操作日志("货币：" + CSm4.加密(新用户.虚拟货币列表[num].id) + "已收到，正在解密");
                                系统日志.添加系统日志("货币：" + CSm4.加密(新用户.虚拟货币列表[num].id) + " 已由用户：" + 新用户.临时id + "发送");
                                新用户.添加操作日志("货币：" + CSm4.加密(新用户.虚拟货币列表[num].id) + "已抵押成功");
                                系统日志.添加系统日志("货币：" + CSm4.加密(新用户.虚拟货币列表[num].id) + " 已由用户：" + 新用户.临时id + "抵押");
                                break;
                            }
                        }
                    }

                    while (true)
                    {
                        while (任务.任务列表.Count == 0)
                        {
                            Thread.Sleep(100);
                        }
                        if (新用户.任务 == null)
                        {
                            Thread.Sleep(100);
                            continue;
                        }
                        else
                            新用户.任务.所属用户 = 新用户;

                        int count = 0;

                        系统日志.添加系统日志("用户：" + 新用户.临时id + "开始执行任务" + 新用户.任务.任务id);
                        while (新用户.联合匿名度(新用户.任务.数据增量) > 新用户.目标匿名度 * 100)
                        {
                            offset = 新用户.sock.Receive(buffer, buffer.Length, SocketFlags.None); // 接收客户端传入的数据
                            string 数据 = Encoding.UTF8.GetString(buffer, 0, offset);
                            Thread.Sleep(全局.感知速度);
                            // if (新用户.任务.任务完成情况 % 2 == 0)
                            新用户.已发送数据量 += 新用户.任务.数据增量;
                            count++;
                            新用户.任务.任务采集列表.Add(数据);
                            新用户.添加操作日志("任务已完成：" + 新用户.任务.任务完成情况.ToString("0.00") + "%，当前匿名度：" + 新用户.联合匿名度().ToString("0.00") + "%");
                            if (新用户.任务.任务完成情况 == 100)
                            {
                                //任务.任务列表.Remove(新用户.任务);
                                任务.删除列表.Add(新用户.任务);
                                任务.已完成任务++;
                                break;
                            }
                        }
                        foreach (虚拟货币 i in 虚拟货币.产生虚拟货币(新用户, 1 + 新用户.任务.激励金额 * count / 新用户.任务.数据量))
                        {
                            新用户.添加操作日志("已发放激励：" + i.id);
                            系统日志.添加系统日志("已发放激励：" + i.id + "给用户：" + 新用户.临时id);
                            虚拟货币.已发放激励++;
                        }
                        foreach (虚拟货币 i in 新用户.任务.抵押货币)
                        {
                            新用户.添加操作日志("已归还抵押：" + i.id);
                            系统日志.添加系统日志("已归还抵押：" + i.id + "给用户：" + 新用户.临时id);
                        }
                        新用户.任务.抵押货币.Clear();

                        if (新用户.任务.任务完成情况 == 100)
                        {
                            新用户.添加操作日志("任务完成");
                            系统日志.添加系统日志("任务：" + 新用户.任务.任务id + "已做完");
                            新用户.任务.所属用户 = null;
                        }
                        else
                        {
                            新用户.添加操作日志("已达到匿名度阈值，任务结束");
                            系统日志.添加系统日志("任务：" + 新用户.任务.任务id + " 已完成" + 新用户.任务.任务完成情况.ToString("0.00") + "%");
                            新用户.任务.所属用户 = null;
                        }

                        while (任务.任务列表.Count == 0)
                        {
                            Thread.Sleep(100);
                        }
                        if (新用户.任务 == null)
                        {
                            Thread.Sleep(100);
                            continue;
                        }
                        while (可分配任务.Count == 0)
                        {
                            可分配任务 = 任务.任务列表.FindAll(c => c.匿名度 > 新用户.目标匿名度 && 新用户.联合匿名度(c.数据增量) / 100 > 新用户.目标匿名度 && c.任务完成情况 < 100 && c.所属用户 == null);
                            Thread.Sleep(100);
                        }
                        if (可分配任务.Count > 0)
                            新用户.任务 = 可分配任务.First();
                        可分配任务.Clear();
                    }

                    /*用户.用户列表.Remove(新用户);
                    用户.删除列表.Add(新用户);
                    新用户.sock.Close();*/
                }
                catch
                {
                    lock (用户.用户列表)
                        用户.用户列表.Remove(新用户);
                    lock (用户.删除列表)
                        用户.删除列表.Add(新用户);
                    新用户.sock.Close();
                    //Console.Title = "当前用户：" + 用户.用户列表.Count;
                }
            }
        }
    }
}